/*
 * Proxy.h
 *
 *  Created on: 2013. 8. 5.
 *      Author: jjaehuny
 */

#ifndef PROJECTZ_PROXY_H_
#define PROJECTZ_PROXY_H_

#include <string>

#include "NProxy/Static.h"
#include "NProxy/FriendsServer.h"
#include "NProxy/GuildServer.h"

#include "User.h"

//
//namespace ProjectZ {
//class User;
//} /*ProjectZ*/

namespace ProjectZ { namespace NProxy {

struct ProxyType { enum ENUM {
	CACHESERVER,
	LOCATIONSERVER,
	FRIENDSSERVER,
	GUILDSERVER
}; /*ENUM*/ }; /*ProxyType*/

bool GetConnectionInfoFromDB();
bool Connect(ProxyType::ENUM eType, int idx, std::string strIP, int port);


// Proxy 를 사용하기 전 유저 접속이 일어나면 Login 진행 후 호출이 되어야 한다.
bool Initial(User * pUser, int user_seq);
// Proxy 를 사용후 유저 접속이 종료된 경우 호출 되어야 한다.
void Final(User * pUser);
void RemoveUser(int user_seq);

User * GetUser(int user_seq);
const std::map<int, User *>& GetUserTree();

// To Cache Server
bool UserInfoSyn(User * pUser);
bool CharacterInfoSyn(User * pUser, int char_seq);
bool NewCharacterInfoSyn(User * pUser, int char_seq);
bool FlushCharacterInfoSyn(User * pUser, int char_seq, bool flushDB);
bool FlushNewCharacterInfoSyn(User * pUser, int char_seq, int slotindex, bool flushDB);
bool FlushUserInfoSyn(User * pUser, bool flushDB);
bool FlushUserSlotInfoSyn(User * pUser, int slotIndex);

void RemoveUser(User * pUser);
CacheServer* GetCacheServer(int user_seq);
CacheServer* GetCacheServer(User * pUser);
// To Cache Server


// To LocationServer
bool RegistUser(User * pUser);
bool UnRegistUser(User * pUser);
bool UnRegistUser(uint32_t seq);
bool UnRegistUser(int userseq);
bool Chat(User * pUser, int type, int receiver_seq, std::string message);
//bool Recall(User * pUser, int receiver_seq, std::string ip, int port);
bool Recall(User * pUser, int receiver_seq);//, std::string ip, int port);
bool RecallAck(uint32_t user_seq, uint32_t receiver_seq, uint16_t is_accept);
void TradeItemSoldout(User * pUser, int recv_userseq, uint64_t tradeseq, int classtype, int sheettype);
bool SetMainCharacterInfo(User * pUser);
bool GetMainCharacterInfo(User * pUser, int target_seq);
bool GetMainCharacterInfo_V2(User * pUser, int target_seq);
LocationServer* GetLocationServer(int user_seq);
LocationServer* GetLocationServer(User * pUser);
// To LocationServer

// GuildServer
GuildServer * GetGuildServer(User * pUser);
void ApplyGuildPoint(User * pUser, int contents, int value);
void UpdateGuildLoginTime(User * pUser);
const std::map<int, GuildServer *>& GetGuildServerTree();

// To Friends Server
bool FlushFRUserInfoSyn(User * pUser);
void RemoveFRUserSyn(User * pUser);
FriendsServer *GetFriends(const int mod);
FriendsServer* GetFriendsServer(User * pUser);
const std::map<int, FriendsServer *>& GetFriendsTree();


template<typename T> bool SendFriendsServerFirst(User * pUser, T& msg)
{
	if (0 == GetFriendsTree().size())
		return false;

	FriendsServer * pFriendsServer = GetFriendsServer(pUser);
	if (NULL == pFriendsServer)
	{
		return false;
	}

	msg.seq = pUser->GetUserSeq();
	pFriendsServer->SendMessage(msg);
	DEBUGLOG("$$ %s MSG_ID=%d SEQ=%d", __FUNCTION__, msg.MSG_ID, msg.seq);
	return true;
}

template<typename T> bool SendFriendsServer(int userseq, T& msg)
{
	if (0 == GetFriendsTree().size())
		return false;

	int mod = userseq % GetFriendsTree().size();
	FriendsServer * pFriendsServer = GetFriends(mod);
	if (NULL == pFriendsServer)
	{
		return false;
	}

	msg.seq = userseq;
	pFriendsServer->SendMessage(msg);
	DEBUGLOG("$$ %s MSG_ID=%d SEQ=%d", __FUNCTION__, msg.MSG_ID, msg.seq);
	return true;
}
// To Friends Server

template<typename T> bool SendGuildServer(User * pUser, T& msg)
{
	GuildServer * pGuildServer = GetGuildServer(pUser);
	if (NULL == pGuildServer)
	{
		DEBUGLOG("%s : pGuildServer is NULL, msg_id = %d", __FUNCTION__, msg.MSG_ID);
		return false;
	}

	pGuildServer->SendMessage(msg);

	return true;
}

} /*NProxy*/ } /*ProjectZ*/


#endif /* PROJECTZ_PROXY_H_ */
